Ext.define('App.lib.Treeselector', {
    extend: 'Ext.container.Container',
    xtype: 'treeselector',
    alias : 'widget.treeselector',
    mixins: [
//        'Ext.util.StoreHolder',
//        'Ext.form.field.Field',
        'Ext.ux.form.MultiSelect'
    ],
//    requires: [
//        'Ext.data.TreeStore',
//        'Ext.layout.container.HBox',
//        'Ext.button.Button',
//        'Ext.ux.form.MultiSelect'
//    ],
    layout: {
        type: 'hbox',
        align: 'stretch'
    },
    hideNavIcons:false,

    buttons: ['top', 'up', 'add', 'remove', 'down', 'bottom'],

    buttonsText: {
        top: "Move to Top",
        up: "Move Up",
        add: "Add to Selected",
        remove: "Remove from Selected",
        down: "Move Down",
        bottom: "Move to Bottom"
    },

    layout: {
        type: 'hbox',
        align: 'stretch'
    },
    initComponent: function(){
    	var me = this;
        me.ddGroup = me.id + '-dd';
    	this.setupItems();
    	this.setValue(this.value);
    	this.callParent();
    },
    setupItems: function(){
    	var me = this;
    	me.fromField = me.fromList(me.fromTitle);
    	me.toField = me.toList(me.toTitle);
    	return me.items = [
	    		me.fromField,
	    		{
			        xtype: 'container',
			        margin: '0 4',
			        layout: {
			            type: 'vbox',
			            pack: 'center'
			        },
			        items: me.createButtons()
	    		}, 
	    		me.toField
    		];
    },
    fromList: function(title){
        var me = this;
        return Ext.create('Ext.tree.Panel', {
	        title: title,
	        flex: 1,
	        rootVisible: me.rootVisible,
	        store: me.store,
	        viewConfig: {
	            plugins: {
	                ptype: 'treeviewdragdrop',
	                dragGroup: me.ddGroup,
	                appendOnly: true,
	                sortOnDrop: true,
	                containerScroll: true
	            }
	        },
	        listeners: {
	        	itemdblclick: function(e, record, item, i){
	        		if(record.isLeaf())
	        			me.moveRec(true, record);
	        	}
            }
	    });
    },
    toList: function(title){
        var me = this;

        return Ext.create('Ext.ux.form.MultiSelect', {
            submitValue: false,
            getSubmitData: function(){
                return null;
            },
            getModelData: function(){
                return null;    
            },
            flex: 1,
            dragGroup: me.ddGroup,
            dropGroup: me.ddGroup,
            title: title,
            store: {
                fields:[],
                data: []
            },
            displayField: me.displayField,
            valueField: me.valueField,
            disabled: me.disabled,
            listeners: {
                boundList: {
                    scope: me,
                    itemdblclick: me.onItemDblClick,
                    drop: function(e, data, record, s, c, i){
                    	
//                    	debugger;
                    	if(data.view.xtype == 'treeview')
                    		me.moveData(true, data.records[0]);
                		me.syncValue
                	},
                	tpl: new Ext.XTemplate('<tpl for=".">asdf{name}</tpl>')
                }
            }
        });
    },
    createButtons: function() {
        var me = this,
            buttons = [];

        if (!me.hideNavIcons) {
            Ext.Array.forEach(me.buttons, function(name) {
                buttons.push({
                    xtype: 'button',
                    tooltip: me.buttonsText[name],
                    handler: me['on' + Ext.String.capitalize(name) + 'BtnClick'],
                    cls: Ext.baseCSSPrefix + 'form-itemselector-btn',
                    iconCls: Ext.baseCSSPrefix + 'form-itemselector-' + name,
                    navBtn: true,
                    scope: me,
                    margin: '4 0 0 0'
                });
            });
        }
        return buttons;
    },
    syncValue: function() {
        var me = this; 
        me.mixins.field.setValue.call(me, me.setupValue(me.toField.store.getRange()));
    },
    onItemDblClick: function(view, rec) {
        this.moveRec(view === this.fromField.boundList, rec);
    },
    setupValue: function(value){
        var delimiter = this.delimiter,
            valueField = this.valueField,
            i = 0,
            out,
            len,
            item;
            
        if (Ext.isDefined(value)) {
            if (delimiter && Ext.isString(value)) {
                value = value.split(delimiter);
            } else if (!Ext.isArray(value)) {
                value = [value];
            }
        
            for (len = value.length; i < len; ++i) {
                item = value[i];
                if (item && item.isModel) {
                    value[i] = item.get(valueField);
                }
            }
            out = Ext.Array.unique(value);
        } else {
            out = [];
        }
        return out;
    },
    moveRec: function(add, recs) {
        var me = this,
            fromField = me.fromField,
            toField   = me.toField,
            fromStore = add ? fromField.store : toField.store,
            toStore   = add ? toField.store   : fromField.store;

        fromStore.suspendEvents();
        toStore.suspendEvents();
        me.moveData(add, recs);
        fromStore.resumeEvents();
        toStore.resumeEvents();
        
        fromField.getView().refresh();
        toField.boundList.refresh();

        me.syncValue();
    },
    moveData: function(add, recs){
    	if(!recs.get('leaf'))
    		return;
        var me = this,
        fromField = me.fromField,
        toField   = me.toField,
        fromStore = add ? fromField.store : toField.store,
        toStore   = add ? toField.store   : fromField.store,
        displayField = me.displayField,
    	parentNode = recs.parentNode;
    	if(add){
    		if(Ext.isDefined(recs.pn))
    			return;
        	toStore.add(Ext.apply(recs, {pn: parentNode}));
            me.toField.boundList.getSelectionModel().select(recs);
        	recs.remove();
        	var text = parentNode.get(displayField);
        	me.showPraentRaw && Ext.isDefined(text) &&
        	recs.set(displayField, text + '       »       ' + recs.get(displayField));
        }
        else{
        	fromStore.remove(recs);
        	recs.pn.appendChild(recs.data);
        	recs.pn.expand();
        	var texts = displayField.split('»');
        	me.showPraentRaw &&
        	recs.set(displayField,recs.get(texts[texts.length - 1].trim()));
        }
    },
    onAddBtnClick : function() {
        var me = this,
            selected = me.fromField.getSelection()[0];

        selected && me.moveRec(true, selected);
    },
    onRemoveBtnClick : function() {
        var me = this,
            selected = me.toField.getSelected()[0];

        selected && me.moveRec(false, selected);
    },
    getSelections: function(list) {
        var store = list.getStore();

        return Ext.Array.sort(list.getSelectionModel().getSelection(), function(a, b) {
            a = store.indexOf(a);
            b = store.indexOf(b);

            if (a < b) {
                return -1;
            } else if (a > b) {
                return 1;
            }
            return 0;
        });
    },

    onTopBtnClick : function() {
        var list = this.toField.boundList,
            store = list.getStore(),
            selected = this.getSelections(list);

        store.suspendEvents();
        store.remove(selected, true);
        store.insert(0, selected);
        store.resumeEvents();
        list.refresh();
        this.syncValue(); 
        list.getSelectionModel().select(selected);
    },

    onBottomBtnClick : function() {
        var list = this.toField.boundList,
            store = list.getStore(),
            selected = this.getSelections(list);

        store.suspendEvents();
        store.remove(selected, true);
        store.add(selected);
        store.resumeEvents();
        list.refresh();
        this.syncValue();
        list.getSelectionModel().select(selected);
    },

    onUpBtnClick : function() {
        var list = this.toField.boundList,
            store = list.getStore(),
            selected = this.getSelections(list),
            rec,
            i = 0,
            len = selected.length,
            index = 0;

        store.suspendEvents();
        for (; i < len; ++i, index++) {
            rec = selected[i];
            index = Math.max(index, store.indexOf(rec) - 1);
            store.remove(rec, true);
            store.insert(index, rec);
        }
        store.resumeEvents();
        list.refresh();
        this.syncValue();
        list.getSelectionModel().select(selected);
    },

    onDownBtnClick : function() {
        var list = this.toField.boundList,
            store = list.getStore(),
            selected = this.getSelections(list),
            rec,
            i = selected.length - 1,
            index = store.getCount() - 1;

        store.suspendEvents();
        for (; i > -1; --i, index--) {
            rec = selected[i];
            index = Math.min(index, store.indexOf(rec) + 1);
            store.remove(rec, true);
            store.insert(index, rec);
        }
        store.resumeEvents();
        list.refresh();
        this.syncValue();
        list.getSelectionModel().select(selected);
    },

    setValue: function(value) {
        var me = this,
            fromField = me.fromField,
            toField = me.toField,
            fromStore = fromField.store,
            toStore = toField.store,
            selected;


        value = me.setupValue(value);
        me.mixins.field.setValue.call(me, value);

        selected = me.getRecordsForValue(value);

        fromStore.suspendEvents();
        toStore.suspendEvents();
        toStore.removeAll();


        Ext.Array.forEach(selected, function(rec){
            me.moveData(true, rec);
        });
        fromStore.resumeEvents();
        toStore.resumeEvents();

        Ext.suspendLayouts();
        fromField.getView().refresh();
        toField.boundList.refresh();
        Ext.resumeLayouts(true);        
    },
    getRecordsForValue: function(value){
        var me = this,
        records = [],
        all = me.fromField.getStore().getData().items,
        valueField = me.valueField,
        i = 0,
        allLen = all.length,
        rec,
        j,
        valueLen;
        
	    for (valueLen = value.length; i < valueLen; ++i) {
	        for (j = 0; j < allLen; ++j) {
	            rec = all[j];   
	            if (rec.get(valueField) == value[i]) {
	                records.push(rec);
	            }
	        }    
	    }
	        
	    return records;
    },
    onBindStore: function(store, initial) {
        var me = this;

        if (me.fromField) {
            me.toField.store.removeAll();
        }
    },

    onEnable: function(){
        var me = this;

        me.callParent();
        me.fromField.enable();
        me.toField.enable();

        Ext.Array.forEach(me.query('[navBtn]'), function(btn){
            btn.enable();
        });
    },

    onDisable: function(){
        var me = this;

        me.callParent();
        me.fromField.disable();
        me.toField.disable();

        Ext.Array.forEach(me.query('[navBtn]'), function(btn){
            btn.disable();
        });
    },

    onDestroy: function(){
        this.bindStore(null);
        this.callParent();
    }
});